package com.codejiwei.core.graphx

import org.apache.spark.graphx.{EdgeTriplet, Graph, VertexId}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.graphx.util.GraphGenerators

object GraphX_ModifyStructure {
  def main(args: Array[String]): Unit = {
    val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("GraphXModifyStructure"))
    val graph: Graph[VertexId, Int] = GraphGenerators.logNormalGraph(sc, numVertices = 10, numEParts = 5, mu = 2.0, sigma = 1.5)
    println(graph.outDegrees.collect().mkString(", "))
    println(graph.inDegrees.collect().mkString(", "))
    //TODO 用于反转图中的所有边，即将所有边的方向颠倒
    val reversedGraph = graph.reverse
    println(reversedGraph.outDegrees.collect().mkString(", "))

    //TODO 用于创建原图的子图，其中包含满足指定条件的顶点和边
    // 定义边谓词函数，保留边属性大于等于 3 的边
    val edgePredicate: EdgeTriplet[VertexId, Int] => Boolean = triplet => triplet.attr >= 3

    // 定义顶点谓词函数，保留顶点属性小于等于 5 的顶点
    val vertexPredicate: (VertexId, VertexId) => Boolean = (v, d) => d <= 5

    // 提取子图，保留满足条件的边和顶点
    val subgraph = graph.subgraph(epred = edgePredicate, vpred = vertexPredicate)

    // 对子图执行一些操作
    val numEdges = subgraph.numEdges
    val numVertices = subgraph.numVertices


    println(numEdges)
    println(numVertices)

    println(subgraph.vertices.collect().mkString(", "))
    println(subgraph.edges.collect().mkString(", "))

    //TODO mask 方法用于使用另一个图作为掩码，过滤原图中的顶点和边。具体来说，对于原图中的每个顶点和边，如果它在另一个图中存在，则保留在结果图中，否则移除。
    val graph1: Graph[Long, Int] = GraphGenerators.logNormalGraph(sc, numVertices = 10, numEParts = 5, mu = 2.0, sigma = 1.5)
    val graph2: Graph[Long, Int] = GraphGenerators.logNormalGraph(sc, numVertices = 10, numEParts = 5, mu = 2.0, sigma = 1.5)

    // 使用 graph2 作为掩码，过滤 graph1 中的顶点和边
    val maskedGraph = graph1.mask(graph2)
    println("Number of vertices in masked graph: " + maskedGraph.numVertices)
    println("Number of edges in masked graph: " + maskedGraph.numEdges)

  }
}
